trigger FulfillmentItemTrigger on Fullfilment_Item__c (before update,before Insert, after insert, after update) {

    list<Fullfilment_Item__c> statusHistoryList = new list<Fullfilment_Item__c>();    
    list<Fullfilment_Item__c> updateOwnersList = new list<Fullfilment_Item__c>();
    List<Fullfilment_Item__c> createTaskList = new List <Fullfilment_Item__c>();
    List<Fullfilment_Item__c> activityHistoryList = new List <Fullfilment_Item__c>();
    List<Fullfilment_Item__c> PIList = new List <Fullfilment_Item__c>();    
    List<Fullfilment_Item__c> escalationList = new list<Fullfilment_Item__c>();
    List<Fullfilment_Item__c> changeRequestFIList=new List<Fullfilment_Item__c>();
    List<Id> fitemIds = new list<Id>();    
    public boolean MovesForwardFunction =false;
    public boolean MovesForwardTask = false;
    public string preFunction;
    public string preTask;
    public decimal preTaskSequence;
        
        
    //Check if before trigger           
    if(Trigger.isBefore) 
    {                      
         //check if before insert
          if(Trigger.isInsert)
          {
              //Workflow assignment for the Fulfillment Item   
                  iFulfillAssignWorkflow.AssignWorkflow(Trigger.new,false);                          
              //Assign priority index id for the Fulfillment Item          
                  iFulfillAssignPriorityIndex.AssignPriorityIndex(Trigger.new); 
              //Assign the Fullfillment Period Value for the FI    
                  iFulfillAssignPriorityIndex.AssignPeriodValue(Trigger.new);
              //Change the status and copy owner name to custom field    
                  iFulfillHandler.copyOwner(trigger.new);
          }          
          //check if before update
          if(Trigger.isUpdate)
          {             
              for(Fullfilment_Item__c FI :Trigger.new)
              {                   
                //Check status and accordingly update the live outed field       
                 
                  if(  FI.Preview_Action__c != null && FI.Preview_Action__c != Trigger.oldMap.get(FI.id).Preview_Action__c)
                  {
                      if(FI.Preview_Action__c.equalsIgnoreCase(IfullfillTextConstant.FI_PREVIEW_OVERRIDE_ACTION )) 
                      {
                          FI.Preview_Status__c = IfullfillTextConstant.FI_PREVIEW_ESIGNED_STATUS;
                          FI.E_Sign_Type__c = IfullfillTextConstant.FI_E_SIGN_OFFLINE_TYPE;
                      }
                      else  if(FI.Preview_Action__c.equalsIgnoreCase(IfullfillTextConstant.FI_PREVIEW_INDUSTRY_STD_ACTION)) 
                      {
                          FI.Preview_Status__c = IfullfillTextConstant.FI_PREVIEW_INDUSTRY_STD_STATUS;
                          FI.E_Sign_Type__c = '';
                      }
                      else  if(FI.Preview_Action__c.equalsIgnoreCase(IfullfillTextConstant.FI_PREVIEW_RECALL_ACTION)) 
                      {
                          FI.Preview_Status__c = IfullfillTextConstant.FI_PREVIEW_CREATED_STATUS;
                          FI.E_Sign_Type__c = '';
                      }
                  }                         
                 // If the Status is 'outed'(coming the status from external system) than update workflow end date to current date.
                 if( (FI.Status__c != null && FI.Status__c != Trigger.oldMap.get(FI.id).Status__c) &&
                       FI.Status__c.equals(IfullfillTextConstant.FI_WORKFLOW_OUTED_STATUS)){                        
                         FI.Workflow_End_Date__c = DateTime.now();
                  }                    
                  //Check status and accordingly update the live outed field       
                  if( (FI.Status__c != Trigger.oldMap.get(FI.id).Status__c && FI.Status__c != null )&&
                           (FI.Status__c.equals(IfullfillTextConstant.FI_WORKFLOW_LIVE_STATUS) || FI.Status__c.equals(IfullfillTextConstant.FI_WORKFLOW_OUTED_STATUS)||FI.Status__c.equals(IfullfillTextConstant.FI_WORKFLOW_CANCELED_STATUS))){                  
                      FI.Live_Outed_Cancel__c =Date.today();
                  }                         
                  //check escalated and accordingly update the date and user info
                  if(FI.Escalated__c && FI.Escalated__c!=Trigger.oldMap.get(FI.id).Escalated__c){
                       FI.Escalation_Date__c =DateTime.Now();
                       FI.Escalated_By__c=UserInfo.getUserId();          
                  }                  
                  //Take up the owner names when it chages
                  if(FI.ownerId != Trigger.oldMap.get(FI.id).ownerid && Trigger.newMap.get(FI.id).Status__c != IfullfillTextConstant.FI_WORKFLOW_QUERY_STATUS ){
                      if(Trigger.oldMap.get(FI.id).Status__c == IfullfillTextConstant.FI_WORKFLOW_LIVE_STATUS || Trigger.oldMap.get(FI.id).Status__c == IfullfillTextConstant.FI_WORKFLOW_OUTED_STATUS || Trigger.oldMap.get(FI.id).Status__c == IfullfillTextConstant.FI_WORKFLOW_CANCELED_STATUS || Trigger.oldMap.get(FI.id).Status__c == IfullfillTextConstant.FI_WORKFLOW_COMPLETE_STATUS ){                                
                            FI.adderror('You cannot change the owner for Complete / Live / Outed / Cancelled fulfillment item');                                               
                            //updateOwnersList.add(FI); 
                     }
                      updateOwnersList.add(FI); 
                  }                                  
                 //Below added to check rework/reject function and task as per req 710                 
                 //Check if function is same, Task progressed
                 if(FI.Previous_Function_Sequence__c ==Trigger.newMap.get(FI.id).Function_Sequence__c ){
                     system.debug('check if enterwd here'+ FI.Previous_Function_Sequence__c +Trigger.newMap.get(FI.id).Function_Sequence__c );                             
                     if(FI.Previous_Task_Sequence__c < Trigger.newMap.get(FI.id).Task_Sequence__c ){ 
                         system.debug('check if entered here'+ FI.Previous_Task_Sequence__c +Trigger.newMap.get(FI.id).Task_Sequence__c );                             
                         FI.Previous_Dashboard__c = FI.Task_Dashboard_Function__c;                                   
                         FI.Previous_Task__c      = FI.Current_Task_Name__c;
                         FI.Previous_Task_Sequence__c = FI.Task_Sequence__c;
                         FI.In_Rework_Reject__c       = null;
                         // MovesForwardFunction = false;
                         MovesForwardTask = true; 
                         system.debug('Moves forward in task'+MovesForwardTask );
                      }
                  }
                 //Else if function has progressed    
                 if(FI.Previous_Function_Sequence__c < Trigger.newMap.get(FI.id).Function_Sequence__c ){
                     MovesForwardFunction = true; 
                     FI.Previous_Dashboard__c     = FI.Task_Dashboard_Function__c;
                     FI.Previous_Task__c          = FI.Current_Task_Name__c;
                     FI.Previous_Task_Sequence__c = FI.Task_Sequence__c;
                     FI.Previous_Function__c      = FI.Current_Function_Name__c;
                     FI.Previous_Function_Sequence__c = FI.Function_Sequence__c;                            
                     FI.In_Rework_Reject__c       = null;
                     //MovesForwardTask = false;  
                     system.debug('Moves forward in Function' +MovesForwardFunction ); 
                 }   
                //check for change in product family
                if(FI.Product_Family__c != Trigger.oldMap.get(FI.id).Product_Family__c)  
                        PIList.add(FI);      
                 }
              
              //call the copyOwner method
              if(updateOwnersList.size() > 0) iFulfillHandler.copyOwner(updateOwnersList);               
              //Call the priority index method
              if(PIList.size() > 0)iFulfillAssignPriorityIndex.AssignPriorityIndex(PIList); 
              
          }                  
                                  
    }

  if(Trigger.isAfter)
  {
      if (Trigger.isInsert) {                                
          for(Fullfilment_Item__c FI :trigger.new){
              if(FI.Current_Step__C != null){
                  fitemIds.add(FI.current_step__c);
                  activityHistoryList.add(FI); 
               }
               if(FI.Related_Case_Id__c !=null && (((String)FI.ownerid).substring(0,3) == '005')
                   && (FI.Transaction_Type__c.equals(IfullfillTextConstant.FI_TRANSACTION_TYPE_CHANGE_REQUEST)
                                  || FI.Transaction_Type__c.equals(IfullfillTextConstant.FI_TRANSACTION_TYPE_ESCALATION))){ 
                                  
                    changeRequestFIList.add(FI);
                   
                }
          }
          //Creating 'Open' Task History Record for Change Request FI.
          if(changeRequestFIList.size()>0){
              iFulfillAssignWorkflow.createOpenStepHistoryForChangeRequest(changeRequestFIList);
           }   
          IfullfillTextConstant.trackActivityCompletion(fitemIds ,activityHistoryList);
          iFulfillTrackTaskHistory.createNewStepHistory(trigger.new);          
          
      }
      if (Trigger.isUpdate) 
      {       
            
          Set<string> activitySet = new Set<string>();
          Set<ID> fiIDs = new Set<ID>();
          string s;
          for(FulFillment_Activities__c FA :[select Id,Fullfilment_Item__c,Wokflow_Steps__c from FulFillment_Activities__c where Fullfilment_Item__c in :trigger.new]){
              s = string.valueof(FA.Fullfilment_Item__c) + string.valueof(FA.Wokflow_Steps__c);
              activitySet.add(s);                                                                            
          }

        // Create Tasks for the Fulfillment ITem based on the condition starts here                       
         for(Fullfilment_Item__c FI :Trigger.new)
         {          
         
                 if(FI.Status__c != Trigger.oldMap.get(FI.id). Status__c && FI.Status__c ==  IfullfillTextConstant.FI_WORKFLOW_OUTED_STATUS)
                 {                
                     fiIDs.add(FI.id);
                 }
                 if(FI.Escalated__c !=null && (FI.Escalated__c != Trigger.oldMap.get(FI.id).Escalated__c) && FI.Escalated__c && ((String)FI.OwnerId).substring(0,3) == IfullfillTextConstant.OWNERVALUE){                
                        createTaskList.add(FI);
                 }
                 else if((FI.Status__c !=null)&& (FI.Status__c  != Trigger.oldMap.get(FI.id).Status__c) && ((String)FI.Status__c).equalsIgnoreCase('Outed') && ((String)FI.OwnerId).substring(0,3) == IfullfillTextConstant.OWNERVALUE){
                        createTaskList.add(FI);                         
                 }
                 else if(FI.Status__c !=null && (FI.Status__c  != Trigger.oldMap.get(FI.id).Status__c) &&((String)FI.Status__c).equalsIgnoreCase('Live')&& ((String)FI.OwnerId).substring(0,3) == IfullfillTextConstant.OWNERVALUE){                         
                        createTaskList.add(FI);                                
                 }                           
                 if(FI.Escalated__c !=null && (FI.Escalated__c != Trigger.oldMap.get(FI.id).Escalated__c) && FI.Escalated__c){                
                    escalationList.add(FI);
                 }
                 //Status and Type check for FSH
                 if(FI.Status__c != Trigger.oldMap.get(FI.id).Status__c || FI.Current_Step__c != Trigger.oldMap.get(FI.id).Current_Step__c|| FI.ownerid != Trigger.oldMap.get(FI.id).ownerid ) {           
                     statusHistoryList.add(FI);                   
                 } 
 
                 //Task check for Activity history record
                 if(FI.Current_Step__C != Trigger.oldMap.get(FI.id).Current_Step__C && (FI.In_Rework_Reject__c==null || FI.In_Rework_Reject__c=='')){
                     s = String.valueof(FI.id) + String.ValueOf(FI.Current_Step__C);
                     if(!activitySet.contains(s)){
                         fitemIds.add(FI.current_step__c);
                         activityHistoryList.add(FI);                          
                     }
                 }                         
                 if(FI.Previous_Function_Sequence__c ==Trigger.newMap.get(FI.id).Function_Sequence__c ){
                     if(FI.Previous_Task_Sequence__c < Trigger.newMap.get(FI.id).Task_Sequence__c ){                                     
                         MovesForwardTask = true;
                     }
                  } 
                 if(FI.Previous_Function_Sequence__c < Trigger.newMap.get(FI.id).Function_Sequence__c ){
                     MovesForwardFunction = true;
                 }                                                                 
         }
         // Whenever user change the FI workflow status to outed the query request and quries must be closed
           iFulfillHandler.closeQueryRequestAndQueries(fiIDs);
         
                if(createTaskList.size()>0){
                     if(iFulfillCreateTask.IsRecursive()){
                        iFulfillCreateTask.createTask(createTaskList,Trigger.oldMap);
                       } 
             }                                   
             if(statusHistoryList.size()>0) iFulfillTrackTaskHistory.trackStatus(statusHistoryList ,MovesForwardFunction,MovesForwardTask, trigger.oldMap   );                         
             if(activityHistoryList.size()>0) {IfullfillTextConstant.trackActivityCompletion(fitemIds ,activityHistoryList);}          
             if(escalationList.size()>0){iFulfillTrackTaskHistory.createNoteOnEscalation(escalationList);}   
    } // isUpdate condition ends   
  } // isAfter condition ends  
 }